package com.eagift.nettyDemo.listener;

import org.springframework.boot.Banner.Mode;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.availability.AvailabilityChangeEvent;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.boot.context.event.ApplicationStartingEvent;
import org.springframework.boot.context.event.SpringApplicationEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.ContextRefreshedEvent;
public class SpringApplicationListener implements ApplicationListener<ApplicationEvent> {


    @Override
    public void onApplicationEvent(ApplicationEvent arg0) {
        //System.out.println(arg0.getClass().getName()+" is trigged");

        /**
         *SpringBoot Application共支持6种事件监听，按顺序分别是：
         *1.ApplicationStartingEvent：在Spring最开始启动的时候触发
         *2.ApplicationEnvironmentPreparedEvent：在Spring已经准备好上下文但是上下文尚未创建的时候触发
         *3.ApplicationPreparedEvent：在Bean定义加载之后、刷新上下文之前触发
         *4.ApplicationStartedEvent：在刷新上下文之后、调用application命令之前触发
         *5.ApplicationReadyEvent：在调用applicaiton命令之后触发
         *6.ApplicationFailedEvent：在启动Spring发生异常时触发
         * 另外：
         * ApplicationRunner和CommandLineRunner的执行在第五步和第六步之间
         * Bean的创建在第三步和第四步之间
         * 在启动类中，执行SpringApplication.run()方法后的代码，会在第六步后执行
         */
        if (arg0.getClass().isAssignableFrom(ApplicationStartingEvent.class)){
            //System.out.println(arg0.getClass().getName()+" is trigged");

        }else if (arg0 instanceof AvailabilityChangeEvent){

        }else if (arg0 instanceof ApplicationReadyEvent){
            /**
             * ApplicationReadyEvent：上下文已经准备ok
             * 这个时候就可以通过ApplicationReadyEvent获取ConfigurableApplicationContext，
             * 然后通过ConfigurableApplicationContext 获取bean的信息。
             */
            System.out.println(arg0.getClass().getName()+" is trigged");

        }else if (arg0 instanceof ApplicationPreparedEvent){
            /**
             * ApplicationPreparedEvent：上下文准备事件。
             * 上下文context已经准备完毕 ，可以通过ApplicationPreparedEvent获取到ConfigurableApplicationContext实例对象。
             * ConfigurableApplicationContext类继承ApplicationContext类，但需要注意这个时候spring容器中的bean还没有被完全的加载，
             * 因此如果通过ConfigurableApplicationContext获取bean会报错的。比如报错：
             *
             * Exception in thread "main" java.lang.IllegalStateException:
             * org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@69b0fd6f has not been refreshed yet
             *
             * 获取到上下文之后，可以将其注入到其他类中，毕竟ConfigurableApplicationContext为引用类型
             */
            System.out.println(arg0.getClass().getName()+" is trigged");
        }else if (arg0 instanceof ContextClosedEvent){

        }else if(arg0 instanceof ContextRefreshedEvent){
            /**
             * 启动的时候出现异常事件
             */
        }else if(arg0 instanceof ApplicationFailedEvent){
            /**
             *上下文准备事件
             */
            System.out.println(arg0.getClass().getName()+" is trigged");
            System.out.println(((ApplicationFailedEvent) arg0).getException());

        }else if (arg0 instanceof ApplicationStartedEvent){
            /**
             * spring boot 启动监听类
             * 可以在SpringApplication启动之前做一些手脚，比如修改SpringApplication实例对象中的属性值
             */
            SpringApplication springApplication = ((ApplicationStartedEvent) arg0).getSpringApplication();
            springApplication.setBannerMode(Mode.OFF);;//关闭banner
            System.out.println(arg0.getClass().getName()+" is trigged");

        }else if (arg0 instanceof ApplicationEnvironmentPreparedEvent){
            /**
             * ApplicationEnvironmentPreparedEvent：环境事先准备，spring boot中的环境已经准备ok
             * 可以通过ApplicationEnvironmentPreparedEvent获取到SpringApplication、ConfigurableEnvironment等等信息，
             * 可以通过ConfigurableEnvironment实例对象来修改以及获取默认的环境信息。
             */
            System.out.println(arg0.getClass().getName()+" is trigged");
        }else if (arg0 instanceof SpringApplicationEvent){

        }

    }
}
